package wiinf;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.FileWriter;

import java.util.HashMap;
import java.util.Vector;
import java.util.jar.JarEntry;
import java.util.jar.JarOutputStream;


import javax.xml.parsers.SAXParser;
import javax.xml.parsers.SAXParserFactory;

import xml.DOMBuilder;
import xml.SAXOpleiding;
import xml.xmlHandler;



/**
 *
 * @author Randy van Heijst & David Roos
 */
public class fileHandler {
    private final File base = new File("afdelingen");
    private File locatie;
    private String[] map, opleidingen;
    private xmlHandler handler;
    private SAXParserFactory factory;
    private DOMBuilder builder = new DOMBuilder();

    /**
     * Aanmaken van een map met de afdeling naamNieuw als map naamNieuw
     * 
     * @param naam Nieuw Naam van de afdeling
     * @return Geeft true terug als map aanmaken is gelukt
     */
    public boolean createMap(String naam){
        locatie = new File(base + "/" + naam);
        if (!locatie.exists()) {
            locatie.mkdir();
            return true;
        }
        return false;
    }

    /**
     * Alle afdelingen ophalen door de map namen op te halen
     *
     * @return Array met alle afdelingen
     */
    public String[] getMap() {
        System.out.println(base.getAbsolutePath());
        map = base.list();
        System.out.println(map.length);
        return map;

    }

    /**
     * Hernoemen van een map bij wijziging van afdeling naam
     *
     * @param naamOud De oude naam van de afdeling
     * @param naamNieuw De nieuwe naam van de afdeling
     * @return Geeft true terug als hernoemen van de map is gelukt
     */
    public boolean updateMap(String naamOud, String naamNieuw) {
        File oud = new File(base + "/" + naamOud);
        File nieuw = new File(base + "/" + naamNieuw);
        if(!nieuw.exists()){
            oud.renameTo(nieuw);
            return true;
        }
        return false;

    }

    /**
     * Verwijdert de map als de afdeling verwijdert moet worden
     *
     * @param naam Naam van de te verwijderen afdeling
     * @return Geeft true terug als verwijderen van de map is gelukt
     */
    public boolean deleteMap(String naam) {
        File s = new File(base + "/" + naam);
        String[] p = s.list();
        if (p.length == 0) {
                s.delete();
                return true;
        } return false;
    }

    /**
     * Haalt alle opleidingen op die bij een bepaalde afdeling horen
     *
     * @param afdeling De afdeling waarvan de opleidingen opgehaald moet worden
     * @return Geeft een array terug met daarin alle opleidingen van de afdeling
     */
    public String[] getOpleiding(String afdeling) {
        locatie = new File(base + "/"+afdeling);
        opleidingen = locatie.list();

        return opleidingen;
    }

    /**
     * Verwijdert de file behorende bij de te verwijderen opleiding
     *
     * @param afdeling De naam van de afdeling waar de opleiding bjhoort
     * @param opleiding De naam van de te verwijderen opleiding
     */
    public boolean deleteOpleiding(String afdeling, String opleiding){
        locatie = new File(base+"/"+afdeling+"/"+opleiding+".xml");
        locatie.delete();

        if(locatie.exists()) {
            return false;
        }
        return true;
    }

    /**
     * Haalt de data op uit de XML file behorende bij een opleiding
     *
     * @param afdeling De afdeling waar de opleiding bij hoort
     * @param opleiding De opleiding waarvan de informatie ogehaald moet worden
     * @return array met daarin de informatie van de opleiding
     */
    public String[] getXMLOpleiding(String afdeling, String opleiding){
        handler = new xmlHandler();
        String[] data = new String[3];
        try {
            factory = SAXParserFactory.newInstance();
            SAXParser saxParser = factory.newSAXParser();
            locatie = new File(base+"/"+afdeling+"/"+opleiding+".xml");
            saxParser.parse(locatie, handler);
        }
        catch(Exception e){
            System.out.println(e);
        }
        
        SAXOpleiding opleidingXML = handler.opleiding;
        data[0] = opleidingXML.getNaam();
        data[1] = opleidingXML.getLocatie();
        data[2] = opleidingXML.getInfo();

        return data;
    }

    /**
     * Update de meegegeven opleiding
     *
     * @param naamOud Oude naam van de opleiding
     * @param naamNieuw Nieuwe naam van de opleiding
     * @param afdeling Naam van de afdeling
     * @param data Data van de opleiding
     * @return Geeft true terug als updaten is gelukt
     */
    public boolean updateOpleiding(String naamOud, String naamNieuw, String afdelingOud, String afdelingNieuw, String[] data) {
        
        if(afdelingOud.equals(afdelingNieuw)) {
            if(!naamOud.equals(naamNieuw)) {
                File oud = new File(base + "/" + afdelingOud + "/" + naamOud + ".xml");
                File nieuw = new File(base + "/" + afdelingOud + "/" + naamOud + ".xml");
                oud.renameTo(nieuw);
            }
            if(writeXML(afdelingOud, naamNieuw, data)) {
                return true;
            }
        }
        else {
            if(writeXML(afdelingNieuw, naamNieuw, data) && deleteOpleiding(afdelingOud, naamOud)) {
                return true;
            }
        }
        return false;
    }

    /**
     * Maakt de XML file voor de opleiding die aangemaakt moet worden
     *
     * @param afdeling De afdeling waar de opleiding bij hoort
     * @param naam De naam van de toe te voegen opleiding
     * @param data Array met daarin de data van de opleiding
     * @return Geeft true terug als opleiding aanmaken is gelukt
     */
    public boolean writeXML(String afdeling, String naam, String[] data) {
        String uri = base.getPath()+"/"+afdeling+"/"+naam+".xml";
        String opleiding = "<opleiding>\n<naam>"+ data[0] +"</naam>\n<locatie>"+ data[1] +"</locatie>\n<info><![CDATA["+ data[2] +"]]></info>\n</opleiding>";
        boolean gelukt = false;

        try {
            FileWriter out = new FileWriter(uri,false);
            out.write(opleiding);
            out.close();
            gelukt = true;
        }
        catch (Exception e) {
            System.out.println(e);
        }

        return gelukt;
    }

    /**
     * Maakt de XML file met alle opleidingen waarvan de cliënt informatie van wil hebben

     * @param address Het adres van de cliënt waar de file naartoe moet
     * @param hm Hashmap met daarin de benodigde afdelingen en bijbehorende opleidingen
     */
    public void createClientXML(String address, HashMap hm) {
        builder.createClientXML(address, hm);
    }

    /**
     * Maakt de XML file met alle opleidingen
     */
    public void createMainXML() {
        
        HashMap<String,Vector> hm = new HashMap();
        String[] afdelingen = getMap();
        
        for(int i = 0; i < afdelingen.length; i++) {
            Vector opleiding = new Vector();
            locatie = new File(base+"/"+afdelingen[i]);
            map = locatie.list();
            for(int j = 0; j < map.length; j++) {
                String s = map[j].replace(".xml", "");
                opleiding.add(s);
            }
            hm.put(afdelingen[i], opleiding);
        }
        builder.createMainXML(hm);
        File a = new File("jarFiles/clientapp");
        int i = a.listFiles().length;
        File[] files;
        files = a.listFiles();
        File[] tobeJared = new File[files.length+1];
        for(int j = 0; j < files.length; j++) {
            tobeJared[j] = files[j];
        }
        
        tobeJared[i] = new File("jarFiles/HHS.xml");
        File archiveFile = new File("jarFiles/WIINF.jar");
        createJarArchive(archiveFile, tobeJared);

    }

    /**
     * Toevoegen van een file aan de cliënt jar
     *
     * @param archiveFile De jar file waar de nieuwe file in moet komen
     * @param tobeJared Array van files die in de jar moeten komen
     */
    public void createJarArchive(File archiveFile, File[] tobeJared) {
        int BUFFER_SIZE = 10240;
        try {
            byte buffer[] = new byte[BUFFER_SIZE];
            // Open archive file
            FileOutputStream stream = new FileOutputStream(archiveFile);
            File f = new File("jarFiles/MANIFEST.MF");
            File[] tobe = {f};
            
            //FileOutputStream stream1 = new FileOutputStream(f);
            //Manifest m = new Manifest("C:/Documents and Settings/David Roos/Bureaublad/MANIFEST.MF");
            
            JarOutputStream out = new JarOutputStream(stream);

            for (int i = 0; i < tobeJared.length; i++) {
                if (tobeJared[i] == null || !tobeJared[i].exists() || tobeJared[i].isDirectory()) {
                    continue; // Just in case...
                }
                System.out.println("Adding " + tobeJared[i].getName());
                // Add archive entry
                JarEntry jarAdd;
                if(tobeJared[i].toString().contains("HHS.xml") || tobeJared[i].toString().contains("WIINF.dtd") ) {
                    jarAdd = new JarEntry(tobeJared[i].getName());
                }else {
                    jarAdd = new JarEntry("clientapp/" + tobeJared[i].getName());
                }

                jarAdd.setTime(tobeJared[i].lastModified());
                out.putNextEntry(jarAdd);
                
                

                // Write file to archive
                FileInputStream in = new FileInputStream(tobeJared[i]);
                while (true) {
                    int nRead = in.read(buffer, 0, buffer.length);
                    if (nRead <= 0) {
                        break;
                    }
                    out.write(buffer, 0, nRead);
                }
                in.close();
            }

            JarEntry s = new JarEntry("META-INF/" + tobe[0].getName());
            s.setTime(tobe[0].lastModified());
            out.putNextEntry(s);
            FileInputStream in1 = new FileInputStream(tobe[0]);
                while (true) {
                    int nRead = in1.read(buffer, 0, buffer.length);
                    if (nRead <= 0) {
                        break;
                    }
                    out.write(buffer, 0, nRead);
                }
            in1.close();
            out.close();
            stream.close();
            System.out.println("Adding completed OK");
        } catch (Exception ex) {
            ex.printStackTrace();
            System.out.println("Error: " + ex.getMessage());
        }
    }

}
